home *** CD-ROM | disk | FTP | other *** search
-
-
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
- /* */
- /* This file contains the code for implementing the cWindow AE object. */
- /* */
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
- /* Include any container or parent class headers here */
- #include "AEPackObject.h"
- #include "AEObjects.h"
- #include "AERegistry.h"
- #include <packages.h>
- #include "ScriptScrap.h"
- #include "Prototypes.h"
-
-
-
- pascal OSErr WindowFromNullAccessor ( DescType desiredClass,
- const AEDesc *container, DescType containerClass, DescType keyForm,
- const AEDesc *keyData, AEDesc *returnedToken, long refCon )
- {
- WindowPtr currWindow = FrontWindow();
- long count = 1;
- long windowNum = 0;
- OSErr err;
- Boolean getAll;
- AEDesc scratchToken;
- Str255 nameKey = "", windowName = "";
- long nameLength;
- Boolean found = false;
-
- switch (keyForm) {
-
- case formAbsolutePosition:
- getAll = false;
- /* Extract the key's value, handling any of the special constant values */
- err = Win_ConvertAbsKey(keyData, &windowNum, &getAll);
- if (err != noErr) return err;
-
- if (getAll)
- return errAEEventFailed; /* We don't handle multiple windows at one time */
-
- currWindow = FindIndexedWindow(windowNum);
- if (currWindow == NULL)
- return errAENoSuchObject;
-
- /* Now, build a token containing this window */
- BuildWindowToken(currWindow, desiredClass, count, returnedToken);
- break;
-
- case formName:
- /* Get the number of bytes in the specified window name */
- nameLength = GetHandleSize(keyData->dataHandle);
- if (nameLength > 255) return errAENoSuchObject;
-
- /* Move the name into a Pascal-style string */
- nameKey[0] = (char)nameLength;
- BlockMove(*(keyData->dataHandle), &nameKey[1], nameLength);
-
- /* Now, search for a window with the same name */
- count = 1;
- while ((currWindow != NULL) && !found) {
- GetWTitle(currWindow, windowName);
- found = IUEqualString(nameKey, windowName) == 0;
- if (found) break; /* Exit the while loop */
- count++;
- currWindow = (WindowPtr)(((WindowPeek)currWindow)->nextWindow);
- }
- if (!found) return errAENoSuchObject;
-
- /* If the window was found, then construct a token to represent it */
- BuildWindowToken(currWindow, desiredClass, count, returnedToken);
- break;
-
- default:
- return errAEEventNotHandled;
- }
-
- return noErr;
- } /* WindowFromNull */
-
-
- /* Property from object accessors */
- pascal OSErr PropertyFromWindowAccessor ( DescType desiredClass,
- const AEDesc *container, DescType containerClass, DescType keyForm,
- const AEDesc *keyData, AEDesc *returnedToken, long refCon )
- {
- OSErr err = noErr;
- Boolean ok;
- DescType requestedProperty;
-
- if ((keyForm != formPropertyID) || (keyData->descriptorType != typeType))
- return errAECantSupplyType;
-
- if ((container->descriptorType != cWindow) && (container->descriptorType != cDocument))
- return errAETypeError;
-
- requestedProperty = **(DescType**)keyData->dataHandle;
-
- /* Check to see if this is a legal property code for this object class */
- ok = false;
- switch (requestedProperty) {
- /* read-only properties common to cWindow and cDocument */
- case pBestType:
- case pClass:
- case pDefaultType:
- ok = true;
- break;
-
- /* read-only properties unique to cWindow */
- case pHasCloseBox:
- case pHasTitleBar:
- case pIsFloating:
- case pIsModal:
- case pIsResizable:
- case pIsZoomable:
- if (containerClass == cWindow)
- ok = true;
- break;
-
- /* read-only properties unique to a cDocument */
- case pIsModified:
- if (containerClass == cDocument)
- ok = true;
- break;
-
- /* modifiable properties common to cWindow and cDocument */
- case pName:
- ok = true;
- break;
-
- /* modifiable properties unique to cWindow */
- case pBounds:
- case pIndex:
- case pIsZoomed:
- case pSelection:
- case pVisible:
- if (containerClass == cWindow)
- ok = true;
- break;
- }
-
- if (ok) {
- /* Copy the container and convert it into a property token */
- err = AEDuplicateDesc(container, returnedToken);
- if (err == noErr) {
- tokenFlags(*returnedToken) = kPropToken;
- tokenPropCode(*returnedToken) = requestedProperty;
- }
- return err;
- } else
- return errAENoSuchObject; /* We really want "not a property", but that isn't defined */
- } /* PropertyFromWindowAccessor */
-
-
- /* === Handy utilities === */
-
- long CountWindows()
- {
- WindowPtr currWindow = FrontWindow();
- long count = 0;
-
- while (currWindow != NULL) {
- count++;
- currWindow = (WindowPtr)(((WindowPeek)currWindow)->nextWindow);
- }
- return count;
- } /* CountWindows */
-
-
- long GetWindowIndex(WindowPtr theWindow)
- /* Given a windowPtr, return its index (frontmost window = 1, next back = 2, etc.) */
- {
- WindowPtr currWindow = FrontWindow();
- long count = 1;
-
-
- while (currWindow != theWindow) {
- if (currWindow == NULL)
- return 0;
- count++;
- currWindow = (WindowPtr)(((WindowPeek)currWindow)->nextWindow);
- }
- return count;
- } /* GetWindowIndex */
-
-
- WindowPtr FindIndexedWindow(long index)
- /* This routine searches the window list for the window with the specified index */
- /* This is used in conjunction with Win_CreateElement to indicate where the new */
- /* window should go. */
- {
- WindowPeek result;
-
- if (index <= 0)
- result = (WindowPeek)-1; /* Special value for "in front of the frontmost window" */
- else {
- result = (WindowPeek)FrontWindow();
- while ((index > 1) && (result != NULL)) {
- if (result->visible)
- --index;
- result = result->nextWindow;
- }
- }
- return (WindowPtr)result;
- }
-
-
- OSErr Win_ConvertAbsKey(const AEDesc *keyData, long *index, Boolean *getAll)
- /* This routine extracts the value from a formAbsolutePosition key, including the special */
- /* "first", "last", any", "all", and "middle" constants. */
- {
- long numWindows = CountWindows();
- long rawIndex;
-
- /* There are 3 flavors of formAbsolutePosition key -- typeIndexDescriptor (position 1, 2, 3…), */
- /* typeRelativeDescriptor (1 from the beginning, 2 from the beginning, 1 from the end (-1), */
- /* 2 from the end (-2), etc.) or typeAbsoluteOrdinal (first, last, middle, any, and all). */
- /* We'll handle each of these forms in turn */
-
- *getAll = FALSE;
- rawIndex = **((long**)keyData->dataHandle); /* Get the number out of the key */
- switch (keyData->descriptorType) {
- case typeRelativeDescriptor:
- if (rawIndex < 0)
- /* A negative value means "the Nth object from the end", */
- /* i.e. -1 == the last object */
- rawIndex = numWindows + rawIndex + 1;
- /* Otherwise the number is positive, and we treat it like a regular index */
- break;
-
- case typeAbsoluteOrdinal:
- if (rawIndex == kAEFirst)
- rawIndex = 1;
- else if (rawIndex == kAELast)
- rawIndex = numWindows;
- else if (rawIndex == kAEMiddle)
- rawIndex = numWindows / 2;
- else if (rawIndex == kAEAny) {
- if (numWindows <= 1) /* 0 or 1 windows */
- rawIndex = numWindows;
- else
- /* Get a random number between 1 and numWindows */
- rawIndex = 1 + ((unsigned long)Random() * (numWindows - 1)) >> 16;
- }
- else if (rawIndex == kAEAll)
- *getAll = TRUE;
- break;
-
- case typeIndexDescriptor:
- /* The proper number is already in "rawIndex" */
- break;
- }
-
- /* Make sure the returned value is in range */
- *index = (rawIndex < 1) ? 1: rawIndex; /* If rawIndex is 0 or negative, return 1 */
- if (rawIndex > numWindows) /* Make sure it's not too large either */
- return errAENoSuchObject;
- else
- return noErr;
- } /* Win_ConvertAbsKey */
-
-
- void BuildWindowToken(const WindowPtr theWindow, DescType desiredClass, long index, AEDesc *theToken)
- {
- AEDesc nullContainer = {'null', NULL};
- wiHand info = (wiHand)GetWRefCon(theWindow);
-
- theToken->descriptorType = desiredClass;
- theToken->dataHandle = NewHandleClear(sizeof(ourToken));
- tokenDispatchClass(*theToken) = desiredClass;
- tokenFlags(*theToken) = kObjectToken;
- tokenObjectIndex(*theToken) = index;
- tokenWindow(*theToken) = theWindow;
- tokenFRefNum(*theToken) = (*info)->fRefNum;
-
- }
-
-
- /* Token resolvers -- read, write, insert, delete */
-
- /* Individual event handlers */
-
- OSErr Win_CreateElement(AppleEvent *message, AppleEvent *reply, DescType insertionPos, /* <- this is normally the refCon */
- AEDesc *token, AEDesc *replyObject)
- {
- OSErr err = noErr;
- AEDesc nullContainer = {'null', 0L};
- AEDesc keyData = {'null', 0L};
- WindowPtr behindWindow;
- long index;
- WindowPtr doc_wind = 0L;
-
- /* We've been asked for a new window or document. So create one in the */
- /* appropriate layer on the screen */
- switch (insertionPos) {
- case kAEBeginning:
- behindWindow = (WindowPtr)-1L;
- index = 1;
- break;
-
- case kAEEnd:
- behindWindow = NULL;
- index = CountWindows();
- break;
-
- case kAEBefore:
- if (token->dataHandle == NULL)
- return errAETypeError;
- index = tokenObjectIndex(*token);
- behindWindow = FindIndexedWindow(index - 1);
- break;
-
- case kAEAfter:
- if (token->dataHandle == NULL)
- return errAETypeError;
- index = tokenObjectIndex(*token) + 1;
- behindWindow = FindIndexedWindow(index);
- break;
-
- case kAEReplace:
- default:
- return errAEEventFailed; /* We won't allow a new window to replace an existing one */
- }
-
- NewDisplayWindow(NULL); // <<< Potential addition: get a file alias from the "data" parameter
- doc_wind = FrontWindow();
- if ( IsValidPointer ( doc_wind ) )
- AECreateDesc(typeIndexDescriptor, (Ptr)&index, sizeof(index), &keyData);
- else
- err = MemError();
-
- if (keyData.dataHandle != 0L) {
- /* Package everything up into an object specifier. */
- err = CreateObjSpecifier(cWindow, &nullContainer, formAbsolutePosition, &keyData, true, replyObject);
- }
- return err;
- } /* Win_CreateElement */
-
-
- OSErr Win_GetData(AppleEvent *message, AppleEvent *reply, long refcon,
- AEDesc *token, AEDesc *replyObject)
- {
- return Win_ReadTokenData(token, replyObject);
- } /* Win_GetData */
-
-
- OSErr Win_SetData(AppleEvent *message, AppleEvent *reply, long refcon,
- AEDesc *token, AEDesc *replyObject)
- {
- AEDesc theData;
- OSErr err;
-
- err = AEGetKeyDesc(message, keyAEData, typeWildCard, &theData);
- if (err == noErr) {
- /* We don't handle passing in the data as an object specifier yet */
- if (theData.descriptorType = typeObjectSpecifier) {
- return errAECantHandleClass;
- }
- err = Win_WriteTokenData(token, &theData);
- (void)AEDisposeDesc(&theData);
- }
- return err;
- } /* Win_SetData */
-
-
- OSErr Win_Close(AppleEvent *message, AppleEvent *reply, long refcon,
- AEDesc *token, AEDesc *replyObject)
- {
- WindowPtr theWindow = tokenWindow(*token);
-
- CloseAWindow(theWindow);
- return noErr;
-
- } /* Win_Close */
-
-
- OSErr Win_ReadTokenData(const AEDesc *theToken, AEDesc *tokenContents)
- {
- DescType scratchType;
- Boolean scratchBool;
- WindowPtr theWindow;
- DescType propCode,
- objClass;
- OSErr err = noErr;
- AEDesc keyData,
- nullDesc = {'null', NULL};
- AEDesc scratchDesc;
- long documentNumber;
-
- /* Get the thing pointed to by a property or object token */
- theWindow = tokenWindow(*theToken);
- objClass = tokenDispatchClass(*theToken);
- if (tokenFlags(*theToken) & kPropToken) {
- /* Return any readable properties */
- propCode = tokenPropCode(*theToken);
-
- switch (propCode) {
- case pClass:
- return AECreateDesc(typeType, (Ptr)&objClass, sizeof(objClass), tokenContents);
- break;
-
- case pBestType:
- case pDefaultType:
- scratchType = typeObjectSpecifier;
- return AECreateDesc(typeType, (Ptr)&scratchType, sizeof(scratchType), tokenContents);
- break;
-
- case pHasTitleBar:
- /* Yes Virginia, there is a Title Bar */
- scratchBool = true;
- return AECreateDesc(typeBoolean, (Ptr)&scratchBool, sizeof(scratchBool), tokenContents);
- break;
-
- case pHasCloseBox:
- case pIsFloating:
- case pIsModal:
- case pIsResizable:
- case pIsZoomable:
- case pIsZoomed:
- /* None of the above properties are true */
- scratchBool = false;
- return AECreateDesc(typeBoolean, (Ptr)&scratchBool, sizeof(scratchBool), tokenContents);
- break;
-
- case pVisible:
- /* We'll have to check the window… */
- scratchBool = ((WindowPeek)theWindow)->visible;
- return AECreateDesc(typeBoolean, (Ptr)&scratchBool, sizeof(scratchBool), tokenContents);
- break;
-
- case pIsModified:
- /* Our file is automatically saved any time a change is made, so this is */
- /* always false. */
- scratchBool = false;
- return AECreateDesc(typeBoolean, (Ptr)&scratchBool, sizeof(scratchBool), tokenContents);
- break;
-
- case pName: {
- /* Get the title of the selected window and return that */
- Str255 windowName;
-
- GetWTitle(theWindow, windowName);
- return AECreateDesc(typeChar, (Ptr)&windowName[1], *windowName, tokenContents);
- } break;
-
- case pSelection: {
- /* If we have a current selection, return an object specifier for it. */
- /* Otherwise, return null */
- wiHand info = (wiHand)GetWRefCon(theWindow);
- AEDesc nullContainer = {typeNull, NULL};
- AEDesc keyData, docContainer;
- long index;
-
- if ((*info)->numEntries == 0) {
- /* There's no selection, so return a null descriptor */
- *tokenContents = nullContainer;
- } else {
- /* Return an object specifier for the currently visible entry */
- /* The specifier will be "entry n of document m" */
- index = GetWindowIndex(theWindow);
- err = CreateOffsetDescriptor(index, &keyData);
- if (err != noErr) return err;
- err = CreateObjSpecifier(cDocument, &nullContainer, formAbsolutePosition, &keyData, true, &docContainer);
- /* We don't have to dispose of the container or key data because CreateObjSpecifier does that for us */
- if (err == noErr) {
- /* We have the "document m" part, now complete the object specifier */
- index = (*info)->currEntryNum;
- err = CreateOffsetDescriptor(index, &keyData);
- if (err == noErr) {
- err = CreateObjSpecifier(cEntry, &docContainer, formAbsolutePosition, &keyData, true, tokenContents);
- }
- }
- }
- } break;
-
- }
- }
- else
- if (tokenFlags(*theToken) & kObjectToken) {
- /* The default representation for a window or document is an object specifier */
- long index;
- AEDesc nullContainer = {typeNull, NULL};
-
- /* We want an object specifier of the form "document m" */
- index = GetWindowIndex(theWindow);
- err = CreateOffsetDescriptor(index, &keyData);
- if (err == noErr)
- err = CreateObjSpecifier(cDocument, &nullContainer, formAbsolutePosition, &keyData, true, tokenContents);
- }
- else
- err = errAEEventFailed;
-
- return err;
- }
-
-
- OSErr Win_WriteTokenData(const AEDesc *theToken, const AEDesc *data)
- {
- OSErr err = noErr;
- long numItems, index;
- AEDesc currItemDesc = {'null', NULL};
- AEKeyword theAEKeyword;
- DescType propCode;
- AEDesc coercedData = {'null', NULL};
- WindowPtr theWindow;
-
- propCode = tokenPropCode(*theToken);
- theWindow = tokenWindow(*theToken);
-
- switch(propCode) {
-
- case pBounds: {
- /* Change the bounds of the window. The data should be a QDRect */
- Rect newBounds;
-
- err = AECoerceDesc(data, typeQDRectangle, &coercedData);
- if (err != noErr) {
- newBounds = **(Rect**)coercedData.dataHandle;
- MoveWindow(theWindow, newBounds.left, newBounds.top, false);
- SizeWindow(theWindow, newBounds.right - newBounds.left,
- newBounds.bottom - newBounds.top, true);
- }
- } break;
-
- case pIndex: {
- /* Move this window behind another one */
- long newIndex, currIndex;
- WindowPtr windowInFront;
-
- err = AECoerceDesc(data, typeLongInteger, &coercedData);
- if (err != noErr) {
- newIndex = **(short**)coercedData.dataHandle;
- currIndex = GetWindowIndex(theWindow);
- if (newIndex == currIndex) break; /* We're done, so exit this case */
-
- /* Otherwise, we have to move the window */
- /* Since all we have is a "send behind" call, we have to calculate the */
- /* number of the window we should sit behind. The rules are as follows: */
- /* 1) If we're moving into position 1, use SelectWindow */
- /* 2) If we're moving to a higher index # (further back), move behind */
- /* the window with the destination index number */
- /* 3) Otherwise, move behind the window with an index of (destination - 1) */
-
- if (newIndex == 1)
- SelectWindow(theWindow);
- else {
- if (newIndex > currIndex) {
- windowInFront = FindIndexedWindow(newIndex);
- SendBehind(theWindow, windowInFront);
- HiliteWindow(theWindow, false);
- } else {
- windowInFront = FindIndexedWindow(newIndex - 1);
- SendBehind(theWindow, windowInFront);
- /* required code to keep the window manager happy in this one case */
- PaintOne((WindowPeek)theWindow, ((WindowPeek)theWindow)->strucRgn);
- CalcVis((WindowPeek)theWindow);
- SelectWindow(FrontWindow()); /* This is simple paranoia, but I want to make sure all of the activates happen correctly */
- }
- HiliteWindow(theWindow, false);
- SelectWindow(FrontWindow()); /* This is simple paranoia, but I want to make sure all of the activates happen correctly */
- }
- }
- } break;
-
- case pIsZoomed:
- /* This window isn't zoomable, so this is a no-op */
- break;
-
- case pName: {
- /* Change the name of the window (and the name of the file) */
- /* We don't do this */
- return errAEWriteDenied;
- } break;
-
- case pSelection: {
- /* Set the current selection under program control. */
- /* We don't do this */
- return errAEWriteDenied;
- } break;
-
- case pVisible: {
- /* Show or hide the window. The data should be a char with the value 0 or 1 */
- /* (Since pointers are declared as char*, we don't need to cast) */
- err = AECoerceDesc(data, typeBoolean, &coercedData);
- if (err != noErr) {
- if (**coercedData.dataHandle != 0)
- ShowWindow(theWindow);
- else
- HideWindow(theWindow);
- }
- } break;
-
- default:
- err = errAENotModifiable;
- }
- if (coercedData.dataHandle != NULL)
- (void)AEDisposeDesc(&coercedData);
- return err;
- }
-
-
- OSErr Win_AE_Dispatcher(const AppleEvent *message, AppleEvent *reply, long refCon,
- AEEventClass classID, AEEventID eventID,
- const AEDesc *ospec, const AEDesc *token)
- {
- OSErr err = noErr;
- AEDesc replyDesc = {'null', 0L};
-
- if (classID == kAECoreSuite) {
- switch (eventID) {
- case kAECreateElement:
- err = Win_CreateElement(message, reply, refCon, token, &replyDesc);
- break;
-
- case kAEClose:
- case kAEDelete:
- err = Win_Close(message, reply, refCon, token, &replyDesc);
- break;
-
- case kAEGetData:
- err = Win_GetData(message, reply, refCon, token, &replyDesc);
- break;
-
- case kAEGetDataSize: {
- /* We'll do this one by executing "Get Data" and then returning the */
- /* size of the information. This is not necesarily the most efficient */
- /* way to do things if your returned data is large. */
-
- AEDesc tempDesc = {'null', NULL};
- long dataSize;
-
- err = Win_GetData(message, reply, refCon, token, &tempDesc);
- if (tempDesc.dataHandle != NULL) {
- dataSize = GetHandleSize(tempDesc.dataHandle);
- (void)AECreateDesc(typeLongInteger, (Ptr)&dataSize, sizeof(dataSize), &replyDesc);
- (void)AEDisposeDesc(&tempDesc);
- }
- }
- break;
-
- case kAESetData:
- err = Win_SetData(message, reply, refCon, token, &replyDesc);
- break;
-
- /* Events that we don't do */
- case kAESave: /* Changes are saved automatically */
- case kAERevert:
- case kAEPrint: /* Sorry, no printing */
- case kAEClone: /* These other events are left up to you! */
- case kAECountElements:
- case kAEDoObjectsExist:
- case kAEGetClassInfo:
- case kAEMove:
- case kAEOpen:
- default:
- err = errAEEventNotHandled ;
- }
- }
- else
- err = errAEEventNotHandled;
-
- /* See if we need to return anything */
- if ((err == noErr) && (replyDesc.descriptorType != 'null')
- && (reply->descriptorType != 'null')) { /* Note: if the other side didn't ask for a reply, this could be a null desc */
- err = AEPutParamDesc(reply, keyDirectObject, &replyDesc);
- (void)AEDisposeDesc(&replyDesc);
- }
-
- return err;
- } /* Win_AE_Dispatcher */
-
-